Icterus proyect

Este proyecto forma parte de mi tema de investigación: Distribución geográfica del género Icterus, Brisson, 1760 (Icteridae) y sus implicaciones para la conservación. Que pretende identificar zonas con orígenes compuestos (nodos) para priorizar sitios de protección. El método utiliza trazos que buscan describir patrones de distribución históricos, la intersección de estos trazos se denomina nodos.

Barrera-Moreno, Omar; Escalante, Tania; Rodríguez, Gerardo. Panbiogeografía y modelos digitales de elevación: un caso de estudio con roedores en la Faja Volcánica Transmexicana

Los datos utilizados son registros geográficos de los géneros Icterus, Bursera y Sceloporus obtenidos a partir de búsquedas de presencia en el banco de datos del portal de GBIF (Global Biodiversity Information Facility, www.gbif.org/). Revisi’on previa en portal.

Análisis clúster

Antes de localizar los trazos es importante realizar un análisis clúster, este actúa como un “filtro” que identifica patrones consistentes y repetidos. Su objetivo fundamental es identificar patrones. Esto permite identificar tendencias biogeográficas consistentes en el conjunto de datos (previo a los trazos individuales). El análisis clúster es una forma de análisis donde las observaciones se dividen en grupos significativos que comparten características comunes entre sí.

Icterus graduacauda

¿Existen patrones generales de distribución en mis conjuntos de datos?

Se consultaron 19 bases de datos para el género Icterus, 93 para Bursera y 97 para Sceloporus, para especies distribuidas en México. Inicialmente cada una cuenta con 226 variables, con registros desde el año 1887 hasta 2025. El número de observaciones varía desde 42 hasta 1 943 792.

Icterus spurius
Icterus spurius
Icterus chrysater
Icterus chrysater

Icterus dominicensis

Previo al análisis clúster se debe cuidar la calidad de los datos, realicé una limpieza de errores y bases de datos origen, asi como NA, resultando en 4 639 registros filtrados.

Extracción de variables bioclimáticas

Usando capas raster y vectoriales con información bioclimática y elevación se generó una base de datos con información de cada una de las variables para cada registro georeferenciado y se obtuvo una base con 26 variables.

Aclaramiento de coordenadas

Se encontró un marcado sobremuestreo en los registros, por lo que se realizó un aclaramiento usando la función spthin.

Correlación de variables

Para encontrar que variables pueden sezgar el resultado por estar fuertemente correlacionadas se ejecutó un análisis de correlación de variables usando corrplot.

Clúster Kmeans

Una vez preparados los datos y eliminando las variables correlacionadas del análisis se realizó un anális cluster usando el método kmeans, para encontrar el número de clúster óptimio se utilizó fviz_nbclust, que encuentra varianza dentro de los clusters en función del número de clusters (k).

Visualización de clústers

Código

Librerías

Para una gestión de paquetes más eficiente y reproducible, pacman.

#install.packages("pacman")
library(pacman)
## Warning: package 'pacman' was built under R version 4.5.1
p_load("tidyverse",
       "dplyr",
       "here",
       "readr",
       "rgbif",              #descargar datos de ocurrencias
       "sf",                 #manipulación  de datos vectoriales
       "rworldxtra",         #datos vectoriales de los paises del mundo
       "usethis",            #credenciales  
       "CoordinateCleaner",  #limpieza de coordenadas
       "geodata",            #datos geoespaciales complemenatarios
       "ggspatial",          #auxiliar para visualizar datos espaciales
       "terra",              #datos raster  
       "tidyterra",          #maniipulación de raster
       "paletteer", 
       "cluster",
       "spThin",
       "colorspace",
       "ggcorrplot",         #diagrama de correlaciones 
       "ggplot2",            #graficos  
       "factoextra",         #estimación de clústers
       "ggpubr",             #visualización cluster
       "patchwork",
       "magick",
       "jpeg",
       "grid",
       "cowplot",            #combinar gráficos de ggplot2
       "caret",              #correlacion de variables
       "RColorBrewer")             
#update.packages(ask = FALSE)

Credenciales

Automatiza y permite guardar información sin ser expuesta directamente en el código.

Reiniciar cada vez que se edita.

#usethis::edit_r_environ()

#gbif_user="usuario_gbif"
#gbif_pwd="contraseña_gbif"
#gbif_email="email_gbif"

Consultas

consulta_A <- name_suggest("Icterus")$data 
consulta_1 <- name_backbone("Icterus auratus") 
consulta_2 <- name_backbone("Icterus dominicensis")

Clave

Asignación de keyid para descarga.

keyid <- name_backbone("Icterus auratus")$usageKey
keyid <- name_backbone("Icterus dominicensis")$usageKey

(keyid)

Descarga

Asignar credenciales

Llama el archivo environ y asigna.

#usethis::edit_r_environ() 
#user <- Sys.getenv("gbif_user") 
#pwd <- Sys.getenv("gbif_pwd") 
#email <-Sys.getenv("gbif_email")

Solicitar la descarga

Todas las ocurrencias georeferenciadas, sin problemas de georeferenciacion con estatus presente.

#descarga_gbif <- occ_download( pred("taxonKey", keyid),
#                               pred("hasCoordinate", TRUE),
#                               pred("hasGeospatialIssue", FALSE), 
#                               pred("occurrenceStatus","PRESENT"),
#                               user = user, 
#                               pwd = pwd, 
#                               email = email )

para obtener DOI y ver el estado de la solicitud

#occ_download_wait('0002799-251025141854904')
#print(descarga_gbif)

DOI1: 10.15468/dl.hzpadv

DOI2: 10.15468/dl.hzpadv

importar y descomprimir

#df_gbif2 <- descarga_gbif%>%
#  occ_download_get() %>%
#  occ_download_import()

**para errores en zip, forzar nueva descarga

#df_gbif <- descarga_gbif %>%
#  occ_download_get(overwrite = TRUE) %>% #sobreescribe
#  occ_download_import(path = tempdir())

**para acceder a descargas previas

df_gbif <- occ_download_get('0002799-251025141854904') %>%
 occ_download_import()
## Download file size: 3.65 MB
## file exists & overwrite=FALSE, not overwriting...

Limpieza

Limpieza de coordenadas

Elimina duplicados y ejecuta test para limpiar errores comunes. value = “flagged”

df_cleaning <- df_gbif %>% 
  cc_equ(test = "identical", #"absolute"
         value = "clean")%>% 
  clean_coordinates(tests = c("capitals",
                              "centroids", 
                              "institutions", 
                              "seas",
                              "zeros"),
                    value = "clean",
                    verbose = TRUE)%>% #informe de proceso
  write_csv("R_Icterus/I_data/I_10_clean.csv")
## Testing equal lat/lon
## Removed 0 records.
## Testing coordinate validity
## Flagged 0 records.
## Testing zero coordinates
## Flagged 0 records.
## Testing country capitals
## Flagged 0 records.
## Testing country centroids
## Flagged 0 records.
## Testing sea coordinates
## Reading 'ne_50m_land.zip' from naturalearth...
## Flagged 1263 records.
## 
## Testing biodiversity institutions
## 
## Flagged 65 records.
## 
## Flagged 1328 of 23283 records, EQ = 0.06.

exploración

unique(df_cleaning$countryCode)
## [1] "MX" "BZ"
unique(df_cleaning$basisOfRecord)
## [1] "HUMAN_OBSERVATION"   "PRESERVED_SPECIMEN"  "MATERIAL_CITATION"  
## [4] "OCCURRENCE"          "MACHINE_OBSERVATION"
unique(df_cleaning$institutionCode)
##  [1] "CLO"                       "MLZ"                      
##  [3] "UWBM"                      "MCZ"                      
##  [5] "WFVZ"                      "DMNH"                     
##  [7] "iNaturalist"               ""                         
##  [9] "NABU|naturgucker"          "ANSP"                     
## [11] "IBUNAM"                    "LSUMZ"                    
## [13] "ECOSUR"                    "MZFC-FC-UNAM"             
## [15] "FMNH"                      "KU"                       
## [17] "YPM"                       "CM"                       
## [19] "UAM"                       "UMMZ"                     
## [21] "ENCB-IPN"                  "UJAT"                     
## [23] "NHMUK"                     "Facultad de Ciencias UNAM"

Gráfico por institución

df_cleaning_grf <- df_cleaning %>% 
    ggplot(aes(x = institutionCode, 
             fill = institutionCode))+
  geom_bar()+
  coord_flip()+
  scale_fill_brewer(palette = "Set3")+
  theme_minimal()+
  theme(legend.position = "none")+
  labs(title = "Registros por Institucion",
    x = "Institucion",
    y = "Numero de Registros")
df_cleaning_grf
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Set3 is 12
## Returning the palette you asked for with that many colors

limpieza base de datos y geometrías duplicada

df_clean <- df_cleaning %>%
  filter(!is.na(institutionCode)) %>%
  distinct(decimalLatitude, decimalLongitude, .keep_all = TRUE) %>% #elimina puntos duplicados, keep conserva todas las columnas
  select(gbifID, species, decimalLatitude, decimalLongitude, month, year) %>% #selecciona en el orden dado 
  write_csv("R_Icterus/I_data/I_10_clean.csv")
df_clean
## # A tibble: 5,308 × 6
##       gbifID species         decimalLatitude decimalLongitude month  year
##      <int64> <chr>                     <dbl>            <dbl> <int> <int>
##  1 986089623 Icterus auratus            20.4            -87.3     6  2011
##  2 985132034 Icterus auratus            20.9            -87.0     3  2011
##  3 985124182 Icterus auratus            20.6            -87.1     3  2011
##  4 985035008 Icterus auratus            20.9            -90.4     3  2010
##  5 984936534 Icterus auratus            20.1            -87.5     6  1991
##  6 984824510 Icterus auratus            21.1            -89.6    12  2010
##  7 984714367 Icterus auratus            18.7            -87.7     6  2010
##  8 984187842 Icterus auratus            21.2            -86.8     6  2008
##  9 981904282 Icterus auratus            20.2            -87.5     6  2003
## 10 981574079 Icterus auratus            21.5            -87.7     3  2007
## # ℹ 5,298 more rows

(df_clean)

Mapa inicial

Capas

Dataframe a archivo sf (vectorial), se definen las columnas con las coordenadas y el CRS (Coordinate Reference System) WGS84 - Sistema Geodésico Mundial 1984

shp_clean <- df_clean %>% 
  st_as_sf(coords = c("decimalLongitude", "decimalLatitude"), crs= 4326)

union de df inicial con vector para conservar columnas de coordenadas separadas para el adelgazamiento, quitamos columnas duplicadas y renombramos

shp_clean <- full_join(shp_clean, df_clean, by = "gbifID")%>%
  select(!any_of(c("species.y", "month.y", "year.y")))%>%
  rename(species = species.x,
         month = month.x,
         year = year.x)
shp_clean
## Simple feature collection with 5308 features and 6 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -92.63134 ymin: 17.51397 xmax: -86.71187 ymax: 21.60571
## Geodetic CRS:  WGS 84
## # A tibble: 5,308 × 7
##       gbifID species       month  year             geometry decimalLatitude
##      <int64> <chr>         <int> <int>          <POINT [°]>           <dbl>
##  1 986089623 Icterus aura…     6  2011 (-87.31111 20.39639)            20.4
##  2 985132034 Icterus aura…     3  2011  (-87.04917 20.8625)            20.9
##  3 985124182 Icterus aura…     3  2011 (-87.07667 20.62389)            20.6
##  4 985035008 Icterus aura…     3  2010     (-90.4 20.85917)            20.9
##  5 984936534 Icterus aura…     6  1991   (-87.4978 20.1035)            20.1
##  6 984824510 Icterus aura…    12  2010 (-89.60029 21.09171)            21.1
##  7 984714367 Icterus aura…     6  2010 (-87.70722 18.71611)            18.7
##  8 984187842 Icterus aura…     6  2008 (-86.83361 21.16111)            21.2
##  9 981904282 Icterus aura…     6  2003 (-87.46639 20.20806)            20.2
## 10 981574079 Icterus aura…     3  2007  (-87.67944 21.5125)            21.5
## # ℹ 5,298 more rows
## # ℹ 1 more variable: decimalLongitude <dbl>

capa altura

alt <- worldclim_global(var="elev", res=0.5, path=tempdir())

carga archivos vectoriales de la nube

data(countriesHigh)
Mundo <- st_as_sf(countriesHigh) 

Preparación de mapas

mapa México

map_ini <- ggplot() +
  geom_spatraster(data = alt) +
  geom_sf(data = shp_clean, aes(col = species), col = "#F5191C") +
  scale_fill_paletteer_c("grDevices::terrain.colors",
                         limits = c(0, 5000),
                       na.value = "transparent",
                       guide = "none")+
  coord_sf(xlim = c(-120, -77), ylim = c(32, 10)) +
  annotation_scale(location = "bl",
    width_hint = 0.4,
    unit_category = "metric",
    bar_cols = c("#B5B5B5", "#EBEBEB"),
    text_col = "#B5B5B5",
    line_col = "#F8F5F2")+
  theme_minimal()+
  theme(axis.text = element_text(size = 5))
## <SpatRaster> resampled to 5e+05 cells.
map_ini
## Scale on map varies by more than 10%, scale bar may be inaccurate

acercamiento

map_ini_close <- ggplot()+
  geom_spatraster(data= alt)+
  geom_sf(data= shp_clean, aes(col = species), col="#F5191C")+
  scale_fill_paletteer_c("grDevices::terrain.colors",
                         limits = c(0, 5000),
                         na.value = "transparent",
                          name = "Elevacion (m)", 
                         breaks = seq(0, 5000, by = 1000))+
  coord_sf(xlim = c(-97, -85), ylim = c(25, 15))+
  annotation_north_arrow(
    location = "tr",  # ← Agrega la ubicación (top-right recomendado)
    which_north = "true",
    style = north_arrow_fancy_orienteering(
      fill = c("#F8F5F2", "#EBEBEB"),
      line_col = "#B5B5B5"),
    height = unit(1.2, "cm"),
    width = unit(1.2, "cm")) +
  annotation_scale(
    location = "bl",
    width_hint = 0.4,
    unit_category = "metric",
    bar_cols = c("#B5B5B5", "#EBEBEB"),
    text_col = "#B5B5B5",
    line_col = "#F8F5F2")+
  theme_minimal()
## <SpatRaster> resampled to 5e+05 cells.
map_ini_close

cargar imagen y convertir en objeto ggplot

path <- "R_Icterus/I_data/I_dominicensis.jpeg"
img <- readJPEG(path, native = TRUE)
cow_final <- ggdraw() + 
  draw_image(image = img,
             x = 0.1, y = 0.1,
             scale = 1)
cow_final

mapa combinado

map_dist <- map_ini_close / ( cow_final | map_ini )  + 
  plot_annotation(
    title = "Distribucion de Icterus auratus",
    subtitle = "Registros de ocurrencia sobre modelo de elevacion",
    caption = "Fuente: GBIF")
map_dist
## Scale on map varies by more than 10%, scale bar may be inaccurate

ggsave("R_icterus/I_salidas/map_dist.png",
       plot = map_dist,
       dpi = 300,
       width = 15,
       height = 15,
       units = "in")
## Scale on map varies by more than 10%, scale bar may be inaccurate

(shp_clean,

alt)

Extracción de variables bioclimáticas

Worldclim

Datos ambientales (variables bioclimáticas)

#env <- worldclim_global(var = "bio", res = 0.5, path = "datos_wc")

guardar y asignar rds

#saveRDS(env, "datos_wc/climate/wc2.1_30s/bio_enviromental.rds")
env <- readRDS("datos_wc/climate/wc2.1_30s/bio_enviromental.rds")

renombrar las variables para mayor claridad

sprintf(formato de 2 dígitos)

v_names <- vector()
for(i in 1:19){
  v_names[i] <- paste0("bio_", sprintf("%02d", i)) 
}
v_names
##  [1] "bio_01" "bio_02" "bio_03" "bio_04" "bio_05" "bio_06" "bio_07" "bio_08"
##  [9] "bio_09" "bio_10" "bio_11" "bio_12" "bio_13" "bio_14" "bio_15" "bio_16"
## [17] "bio_17" "bio_18" "bio_19"

asigna nombre con el vector

names(env) <- v_names
names(env)
##  [1] "bio_01" "bio_02" "bio_03" "bio_04" "bio_05" "bio_06" "bio_07" "bio_08"
##  [9] "bio_09" "bio_10" "bio_11" "bio_12" "bio_13" "bio_14" "bio_15" "bio_16"
## [17] "bio_17" "bio_18" "bio_19"

Altura

coordenadas a sf y extracción

coord_elev <- shp_clean
puntos_sf <- st_as_sf(coord_elev, coords = c("lon", "lat"), crs = 4326)

elevaciones <- terra::extract(alt, puntos_sf)

columna elev al shp puntos_sf

puntos_sf$elev <- elevaciones$wc2.1_30s_elev

Bioclimáticas

coordenadas y extracción

coord_bio <- shp_clean
env_icter <- terra::extract(env, coord_bio) #extract, capa ambiental y el lugar al que queremos enviar la información

combina objetos data.frames por columnas horizontalmente

df_icter <- cbind.data.frame(puntos_sf, env_icter)%>%
  filter(!is.na(elev))%>% #quita NA
  select(-ID)%>%
  write_csv("R_Icterus/I_data/I_10_clean.csv")

(df_icter)

Adelgazamiento

**

df_icter <- read.csv("R_Icterus/I_data/I_10_clean.csv")

visualización de ocurrencias

ocurrencias <- ggplot(df_icter, aes(x = decimalLongitude, y = decimalLatitude)) +
  geom_point() +
  labs(x = "Longitud",
    y = "Latitud", 
    title = "Ocurrencias") +
  theme_minimal()
ocurrencias

adelgazamiento

set.seed(123)
thin( loc.data = df_icter,
      lat.col =  "decimalLatitude", long.col = "decimalLongitude", 
      spec.col = "species", 
      thin.par = 10, reps = 100, 
      locs.thinned.list.return = FALSE, 
      write.files = TRUE, 
      write.log.file = FALSE,
      out.dir = here("R_Icterus", "I_data"),
      out.base = "I_10")
## ********************************************** 
##  Beginning Spatial Thinning.
##  Script Started at: Wed Oct 29 06:35:03 2025
## lat.long.thin.count
## 372 373 374 375 376 377 378 
##   2  22  15  32  19   7   3 
## [1] "Maximum number of records after thinning: 378"
## [1] "Number of data.frames with max records: 3"
## [1] "Writing new *.csv files"
## Warning in thin(loc.data = df_icter, lat.col = "decimalLatitude", long.col =
## "decimalLongitude", : Writing new *.csv files to output directory:
## C:/Users/Yas/Desktop/Icterus_proyect/R_Icterus/I_data
## [1] "Writing file: C:/Users/Yas/Desktop/Icterus_proyect/R_Icterus/I_data/I_10_thin1.csv"
## [1] "Writing file: C:/Users/Yas/Desktop/Icterus_proyect/R_Icterus/I_data/I_10_thin2.csv"
## [1] "Writing file: C:/Users/Yas/Desktop/Icterus_proyect/R_Icterus/I_data/I_10_thin3.csv"

visualizar y guardar puntos adelgazados

map_thin <- read_csv("R_Icterus/I_data/I_10_thin1.csv") %>%
  ggplot(aes(decimalLongitude, decimalLatitude)) +
  geom_point(color = "red") +
  labs(x = "Longitud",
    y = "Latitud", 
    title = "Aclaramiento") +
  theme_minimal()
## Rows: 378 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): species
## dbl (2): decimalLongitude, decimalLatitude
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
map_thin

map_spthin <- wrap_plots(ocurrencias, map_thin, nrow = 1) +  # ← wrap_plots explícito
  plot_annotation(title = "Distribucion de Icterus dominicensis")

map_spthin

ggsave("R_icterus/I_salidas/mapthin_10.png",
       plot = map_spthin,
       dpi = 300,
       width = 17,
       height = 9,
       units = "in")

Recuperación de id

asignación de ids y adelgazamiento

inicial <- df_icter
thin1 <-  read_csv("R_Icterus/I_data/I_10_thin1.csv")
## Rows: 378 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): species
## dbl (2): decimalLongitude, decimalLatitude
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

join usando las coordenadas y la especie como clave, “thin1” = “inicial”

icter_spthin <- thin1 %>% 
  left_join(inicial,
            by = c("species" = "species",
                   "decimalLongitude" = "decimalLongitude",
                   "decimalLatitude" = "decimalLatitude" ))%>%
  write_csv("R_Icterus/I_data/I_10_clean.csv")

which(is.na(icter_spthin$gbifID))  #Verificar NAs para buscar errores de no coincidencia
## integer(0)

Cuántos registros se conservaron

Leer el archivos y contar filas

datos_inicial <- nrow(inicial)
datos_fin <-nrow(thin1)
datos_elim <- datos_inicial - datos_fin 
print(paste0("Thin/ Numero inicial: ", datos_inicial, ", eliminados: ", datos_elim, ", Numero final: ", datos_fin))
## [1] "Thin/ Numero inicial: 5092, eliminados: 4714, Numero final: 378"

(icter_spthin)

Correlación de variables

Matriz

subselecciona del data, quita ID y species…

matriz_cor <- cor(subset(icter_spthin, select = -c(species, decimalLatitude, decimalLongitude, month, year, gbifID, geometry))) 

Correlograma

corr <- ggcorrplot(matriz_cor, #matriz de correlacion
                   hc.order = FALSE, 
                   type = "lower", 
                   lab = TRUE, 
                   lab_size = 3, 
                   colors= c("#80FFFF", "#FFF7FF", "#FF80FF"),
                   ggtheme = theme_minimal())+
  labs(title = "Matriz de correlacion para Icterus dominicensis")
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## ℹ The deprecated feature was likely used in the ggcorrplot package.
##   Please report the issue at <https://github.com/kassambara/ggcorrplot/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
corr

ggsave("R_Icterus/I_salidas/corr.png", 
       plot = corr,
       dpi = 300,
       width = 12,   
       height = 9,
       units = "in")

eliminar variables altaamente correlacionadas

var_elim <- findCorrelation(matriz_cor, cutoff = 0.7, names = TRUE)
var_elim
##  [1] "bio_19" "bio_06" "bio_02" "bio_15" "bio_05" "bio_10" "bio_01" "bio_17"
##  [9] "bio_12" "bio_13"
icter_corr <- icter_spthin %>%
 select(-all_of(var_elim))%>%
  write_csv("R_Icterus/I_data/I_10_corr.csv")

(icter_corr)

Clùsters

escalado

df_kmeans <- icter_corr %>%
  select(-month, -year, -gbifID, -geometry, -decimalLongitude, -decimalLatitude) %>%
  select(where(is.numeric)) %>%
  scale() %>%
  as.data.frame()

A medida que aumenta el valor de k, la varianza dentro de los clusters tiende a disminuir. La curva o “codo” indica que más allá agregar más clusters tiene poco valor adicional en términos de reducir la varianza dentro de los clusters.

agrupamiento <- fviz_nbclust(df_kmeans, kmeans, method = "wss") +
  geom_vline(xintercept = 5, linetype = 2)+
  labs(title = "Clusters optimos para I. dominicensis",
       x = "Numero de clusters k",
       y = "Varianza dentro de los clusters")
agrupamiento

ggsave("R_Icterus/I_salidas/I_10_grup.png", 
       plot = agrupamiento,
       dpi = 300,
       width = 12,   
       height = 9,
       units = "in")

búsqueda de clústers (kmeans)

set.seed(123)
icter_kmeans <- kmeans(df_kmeans, 5, nstart = 25)
table(icter_kmeans$cluster)
## 
##   1   2   3   4   5 
##  59 128  77  43  71

Visualización

kmeans_grf <- fviz_cluster(icter_kmeans, data = df_kmeans,
                           palette = c("#0000FF", "#C870FF", "#74C9BC", "#7F8A8F", "#BB173A", "#C4D8F3", "#D33682","#8AD6E4"),
                           ggtheme = theme_minimal())+
  labs(title = "Analisis de Clusters",
    subtitle = "Icterus dominicensis")
kmeans_grf

ggsave("R_Icterus/I_salidas/I_10_kmeans.png", 
       plot = kmeans_grf,
       dpi = 300,
       width = 12,   
       height = 9,
       units = "in")

tomando los datos iniciales(icter_corr) crea una columna cluster (posterior kmeans) y filtra cluster 1

icter_clusters <- icter_corr %>%
  mutate(cluster = icter_kmeans$cluster)%>%
  filter(cluster != 1 ) %>%
  write_csv("R_Icterus/I_data/I_10_kmeans.csv")

cuántos registros se conservaron

datos_ini <- nrow(icter_corr)
datos_fin <-nrow(icter_clusters)
datos_elim <- datos_ini - datos_fin 

print(paste0("Kmeans/ Numero inicial: ", datos_ini, ", eliminados: ", datos_elim, ", Numero final: ", datos_fin))
## [1] "Kmeans/ Numero inicial: 378, eliminados: 59, Numero final: 319"